﻿using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using MyVideoPlayer.Models;
using MyVideoPlayer.Views;
using System.Diagnostics;
using System.IO;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Windows;
using WpfScreenHelper;

namespace MyVideoPlayer.ViewModels
{
    public partial class MultiWinSetViewModel : ObservableObject, IDisposable
    {
        #region 字段

        private MultiWinSetModel _multiWinSetModel;
        private readonly Dictionary<string, MainWindow> _windowMap;
        private MainWindowModel _mainWindowModel;
        private static readonly JsonSerializerOptions CachedJsonSerializerOptions = new() { WriteIndented = true };// 缓存的 JSON 序列化选项
        private readonly IEnumerable<Screen> _screens = Screen.AllScreens; // 获取所有屏幕信息
        public Dictionary<string, MainWindow> WindowMap => _windowMap;
        #endregion

        /// <summary>
        /// 多窗口设置模型提供者，用于单例模式
        /// </summary>
        public static class MultiWinSetModelProvider
        {
            public static MultiWinSetModel Instance { get; } = new MultiWinSetModel();
        }
        /// <summary>
        /// 主窗口模型，用于存储主窗口的状态和数据
        /// </summary>
        public MainWindowModel MainWindowModel
        {
            get => _mainWindowModel;
            set => SetProperty(ref _mainWindowModel, value);
        }

        #region 命令
        public IRelayCommand<object> LoadedCommand { get; }
        public IRelayCommand<object> BrowserCommand { get; }
        public IRelayCommand<object> AutoShowedOnCommand { get; }
        public IRelayCommand<object> AutoShowedOffCommand { get; }
        public IRelayCommand<object> OpenNewWindowCommand { get; }
        public IRelayCommand<object> ShutDownWindowCommand { get; }
        #endregion

        public MultiWinSetModel MultiWinSetModel
        {
            get => _multiWinSetModel;
            set => SetProperty(ref _multiWinSetModel, value);
        }

        /// <summary>
        /// 多窗口设置视图模型构造函数，默认使用MainWindowModel
        /// </summary>
        public MultiWinSetViewModel() : this(new MainWindowModel())
        {

        }
        /// <summary>
        /// 多窗口设置视图模型构造函数，接受一个MainWindowModel参数
        /// </summary>
        /// <param name="mainWindowModel"></param>
        public MultiWinSetViewModel(MainWindowModel mainWindowModel)
        {
            _mainWindowModel = mainWindowModel;
            _windowMap = [];
            _multiWinSetModel = MultiWinSetModelProvider.Instance;

            #region 命令
            LoadedCommand = new RelayCommand<object>(OnLoaded);
            BrowserCommand = new RelayCommand<object>(OnBrowser);
            AutoShowedOnCommand = new RelayCommand<object>(OnAutoShowedyOn);
            AutoShowedOffCommand = new RelayCommand<object>(OnAutoShowedOff);
            OpenNewWindowCommand = new RelayCommand<object>(OnOpenNewWindow);
            ShutDownWindowCommand = new RelayCommand<object>(OnShutDownWindow);
            #endregion
        }
        /// <summary>
        /// 浏览器命令处理方法，暂时未使用
        /// </summary>
        /// <param name="obj"></param>
        private void OnBrowser(object? obj)
        {
            //if (obj is string str && _windowMap.TryGetValue(str, out var win))
            //{
            //    win.Close();
            //    _windowMap.Remove(str);
            //}
        }
        /// <summary>
        /// 窗口加载时处理方法，获取屏幕信息和播放列表信息，并加载多窗口
        /// </summary>
        /// <param name="obj"></param>
        private void OnLoaded(object? obj)
        {
            // 窗口加载时获取屏幕以及播放列表信息
            GetScreenAndPlayListInfo();
            // 根据内容加载窗口
            LoadedMultiWindow();
        }
        /// <summary>
        /// 加载多窗口
        /// </summary>
        public void LoadedMultiWindow()
        {
            foreach (var screen in _multiWinSetModel.Screens)
            {
                if (screen.IsPrimary) continue;
                if (screen.IsAutoShowed)
                {
                    OpenNewMainWindow(screen);
                }
                else
                {
                    MultiWinSetModel.Screens.FirstOrDefault(m => m.Name == screen.Name)!.IsShowed = false;
                }

            }
        }
        /// <summary>
        /// 打开窗口
        /// </summary>
        /// <param name="screen"></param>
        private void OpenNewMainWindow(ScreenInfo screen)
        {
            var screenName = screen.Name!;
            if (!_multiWinSetModel.PlayListFileDic.TryGetValue(screenName, out var dataFilePath)) return;
            if (!File.Exists(dataFilePath))
            {
                // 如果播放列表文件不存在，则创建一个新的空文件
                Directory.CreateDirectory(Path.GetDirectoryName(dataFilePath)!);
                File.WriteAllText(dataFilePath, JsonSerializer.Serialize(new MainWindowModel(), CachedJsonSerializerOptions));
            }

            var jsonData = File.ReadAllText(dataFilePath);
            var mainWindowModel = JsonSerializer.Deserialize<MainWindowModel>(jsonData, CachedJsonSerializerOptions)!;
            var isMaximized = mainWindowModel.SettingModel.IsMaximized;

            var mainWindow = new MainWindow(dataFilePath, false)
            {
                WindowStartupLocation = WindowStartupLocation.Manual
            };

            mainWindow.ContentRendered += (s, e) =>
            {
                SetWindowPosition(mainWindow, screen, isMaximized);
            };

            //关闭窗口时，移除窗口映射
            mainWindow.Closed += (s, e) =>
            {
                // 窗口关闭时，移除窗口映射
                _windowMap.Remove(screenName);
                MultiWinSetModel.Screens.FirstOrDefault(m => m.Name == screenName)!.IsShowed = false;
            };

            mainWindow.Show();
            MultiWinSetModel.Screens.FirstOrDefault(m => m.Name == screenName)!.IsShowed = true;
            _windowMap[screenName] = mainWindow;
        }
        /// <summary>
        /// 设置窗口位置
        /// </summary>
        /// <param name="mainWindow"></param>
        /// <param name="screen"></param>
        /// <param name="isMaximized"></param>
        private static void SetWindowPosition(MainWindow mainWindow, ScreenInfo screen, bool isMaximized)
        {
            var source = PresentationSource.FromVisual(mainWindow);
            var dpiX = source?.CompositionTarget.TransformToDevice.M11 ?? 1.0;
            var dpiY = source?.CompositionTarget.TransformToDevice.M22 ?? 1.0;

            // 先恢复为Normal，确保位置和大小生效
            mainWindow.WindowState = WindowState.Normal;

            if (isMaximized)
            {
                mainWindow.Left = screen.Left / dpiX;
                mainWindow.Top = screen.Top / dpiY;
                mainWindow.Width = screen.Width / dpiX;
                mainWindow.Height = screen.Height / dpiY;
                mainWindow.WindowStyle = WindowStyle.None;
                mainWindow.ResizeMode = ResizeMode.NoResize;
                mainWindow.WindowState = WindowState.Maximized;
            }
            else
            {
                mainWindow.Width = 1200;
                mainWindow.Height = 800;
                mainWindow.Left = screen.Left / dpiX + (screen.Width / dpiX - mainWindow.Width) / 2;
                mainWindow.Top = screen.Top / dpiY + (screen.Height / dpiY - mainWindow.Height) / 2;
                mainWindow.WindowStyle = WindowStyle.SingleBorderWindow;
                mainWindow.ResizeMode = ResizeMode.CanResize;
                mainWindow.WindowState = WindowState.Normal;
            }
        }
        /// <summary>
        /// 开启自动显示窗口
        /// </summary>
        /// <param name="obj"></param>
        private void OnAutoShowedyOn(object? obj)
        {
            if (obj is string str)
            {
                MultiWinSetModel.Screens.FirstOrDefault(m => m.Name == str)!.IsAutoShowed = true;
            }
        }
        /// <summary>
        /// 关闭自动显示窗口
        /// </summary>
        /// <param name="obj"></param>
        private void OnAutoShowedOff(object? obj)
        {
            if (obj is string str)
            {
                MultiWinSetModel.Screens.FirstOrDefault(m => m.Name == str)!.IsAutoShowed = false;
            }
        }
        /// <summary>
        /// 打开新的窗口
        /// </summary>
        /// <param name="obj"></param>
        private void OnOpenNewWindow(object? obj)
        {
            if (obj is not string str) return;
            var screen = _multiWinSetModel.Screens.FirstOrDefault(m => m.Name == str);
            if (screen == null || screen.IsShowed) return; // 已显示则不再打开
            OpenNewMainWindow(screen);
        }
        /// <summary>
        /// 关闭窗口
        /// </summary>
        /// <param name="obj"></param>
        private void OnShutDownWindow(object? obj)
        {
            if (obj is string str && _windowMap.Remove(str, out var win))
            {
                win.Close();
                var screen = _multiWinSetModel.Screens.FirstOrDefault(m => m.Name == str);
                if (screen != null) MultiWinSetModel.Screens.FirstOrDefault(m => m.Name == str)!.IsShowed = false;
            }
        }

        [GeneratedRegex(@"[a-zA-Z0-9]+")]
        private static partial Regex DeviceNameRegex();
        public void Dispose()
        {
            _windowMap.Clear();
            SavePlayListData(); // 保存
            GC.SuppressFinalize(this);
        }
        /// <summary>
        /// 异步保存播放列表数据
        /// </summary>
        /// <returns></returns>
        public void SavePlayListData()
        {
            try
            {
                var multiWinSetData = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "MyVideoPlayer", $"MultiWinSetData.json");
                var json = JsonSerializer.Serialize(_multiWinSetModel, CachedJsonSerializerOptions);
                File.WriteAllText(multiWinSetData, json);
            }
            catch (Exception ex)
            {
                Debug.WriteLine("保存播放数据失败: " + ex.Message);
            }
        }
        /// <summary>
        /// 获取屏幕信息
        /// </summary>
        /// <returns></returns>
        private void GetScreenAndPlayListInfo()
        {
            // 读取MultiWinSetData.json文件中的屏幕信息
            var multiWinSetData = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "MyVideoPlayer", $"MultiWinSetData.json");
            if (!File.Exists(multiWinSetData))
            {
                Directory.CreateDirectory(Path.GetDirectoryName(multiWinSetData)!);
                var json = JsonSerializer.Serialize(_multiWinSetModel, CachedJsonSerializerOptions);
                File.WriteAllText(multiWinSetData, json);
            }
            else
            {
                var jsonData = File.ReadAllText(multiWinSetData);
                // 反序列化MultiWinSetModel,此处不能换成_multiWinSetModel，因为如果换成_multiWinSetModel，则会导致多窗口设置无法正确加载，主要是不通知UI更新
                MultiWinSetModel = JsonSerializer.Deserialize<MultiWinSetModel>(jsonData, CachedJsonSerializerOptions)!;
                // 有多的屏幕信息，则需要对比，多的要移除
                var validNames = _screens.Select(s => DeviceNameRegex().Match(s.DeviceName).Value).ToHashSet();
                foreach (var name in _multiWinSetModel.Screens.Select(m => m.Name).ToList())
                {
                    if (!validNames.Contains(name!))
                    {
                        _multiWinSetModel.Screens.Remove(_multiWinSetModel.Screens.First(m => m.Name == name));
                        _multiWinSetModel.PlayListFileDic.Remove(name!);
                    }
                }
            }
            //检查是否有新的屏幕信息，如果有，则添加
            _screens.ToList().ForEach(screen =>
            {
                var screenName = DeviceNameRegex().Match(screen.DeviceName).Value;
                var playListData = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "MyVideoPlayer", $"PlayList_{screenName}.json");
                // 添加播放列表文件
                _multiWinSetModel.PlayListFileDic[screenName!] = playListData;

                if (!_multiWinSetModel.Screens.Any(m => m.Name == screenName))
                {
                    _multiWinSetModel.Screens.Add(new ScreenInfo
                    {
                        Name = screenName,
                        Left = screen.WorkingArea.Left,
                        Top = screen.WorkingArea.Top,
                        Width = screen.WorkingArea.Width,
                        Height = screen.WorkingArea.Height,
                        IsShowed = screen.Primary, // 默认未显示
                        IsAutoShowed = screen.Primary,
                        IsPrimary = screen.Primary
                    });
                }
            });
        }

        public int GetAutoShowedScreenCount()
        {
            return _multiWinSetModel.Screens.Count(m => m.IsAutoShowed == true) - 1;
        }
    }
}
